import { ref } from 'vue'
import { Point, Data } from './types'
export default () => {
  const el = ref<HTMLCanvasElement>()
  const ctx = ref<CanvasRenderingContext2D | null>(null)
  const CANVAS_WIDTH = 300
  const CANVAS_HEIGHT = 300
  const lineStyle = ref('')
  const lineWidth = ref('')
  const reportURL = ref('')
  let isDrawing = false
  const allowDownload = ref(false)
  const pre = ref<Data[]>([])
  const next = ref<ImageData[]>([])

  const drawLine = (point: Point, lineType: boolean) => {
    lineType
      ? ctx.value!.moveTo(point.x, point.y)
      : ctx.value!.lineTo(point.x, point.y)
  }

  const initCanvasCtx = (canvas: HTMLCanvasElement) => {
    ctx.value = canvas.getContext('2d')!
    pre.value.push({
      id: new Date().getTime(),
      data: ctx.value.getImageData(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT),
    })
  }

  const getTouchLinePoint = (el: HTMLCanvasElement, e: TouchEvent) => {
    const { top, left } = el.getBoundingClientRect()
    const { pageX, pageY } = e.touches[0]
    const x = pageX - left
    const y = pageY - top
    console.log('point:', x, y)
    return {
      x,
      y,
    }
  }

  const getMouseLintPoint = (el: HTMLCanvasElement, e: MouseEvent) => {
    const { top, left } = el.getBoundingClientRect()
    const { pageX, pageY } = e
    const x = pageX - left
    const y = pageY - top
    return {
      x,
      y,
    }
  }

  const handleMouseDown = (e: MouseEvent) => {
    isDrawing = true
    const point = getMouseLintPoint(el.value as HTMLCanvasElement, e)
    drawLine(point, true)
    ctx.value!.beginPath()
  }
  const handleMouseMove = (e: MouseEvent) => {
    if (isDrawing) {
      ctx.value!.strokeStyle = lineStyle.value
      ctx.value!.lineWidth = +lineWidth.value
      const point = getMouseLintPoint(el.value as HTMLCanvasElement, e)
      drawLine(point, false)
      ctx.value?.stroke()
    }
  }
  const handleMouseUp = () => {
    isDrawing = false
    ctx.value!.closePath()
    pre.value.push({
      id: new Date().getTime(),
      data: ctx.value!.getImageData(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT),
    })
    next.value = []
  }

  const handleTouchStart = (e: TouchEvent) => {
    isDrawing = true
    const point = getTouchLinePoint(el.value as HTMLCanvasElement, e)
    drawLine(point, true)
    ctx.value!.beginPath()
  }
  const handleTouchMove = (e: TouchEvent) => {
    if (isDrawing) {
      ctx.value!.strokeStyle = lineStyle.value
      ctx.value!.lineWidth = +lineWidth.value

      const point = getTouchLinePoint(el.value as HTMLCanvasElement, e)
      drawLine(point, false)

      ctx.value?.stroke()
    }
  }
  const handleTouchEnd = () => {
    isDrawing = false
    ctx.value!.closePath()
    pre.value.push({
      id: new Date().getTime(),
      data: ctx.value!.getImageData(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT),
    })
    next.value = []
  }

  const handleRemove = () => {
    ctx.value?.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT)
    reportURL.value = ''
    pre.value.push({
      id: new Date().getTime(),
      data: ctx.value!.getImageData(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT),
    })
    next.value.push(
      ctx.value?.getImageData(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT) as ImageData
    )
  }

  const handleSave = (_: Event, type = 'png') => {
    if (!allowDownload.value) return
    const url = el.value?.toDataURL(`image/${type}`) as string
    reportURL.value = url
    const link = document.createElement('a')
    const stamp = new Date().getTime()
    link.download = `canvas-${stamp}.${type}`
    link.href = url
    link.click()
  }

  const handlePrevious = () => {
    if (pre.value.length > 1) {
      ctx.value?.putImageData(
        pre.value[pre.value.length - 2].data as ImageData,
        0,
        0
      )
      next.value.push(pre.value[pre.value.length - 1].data as ImageData)
      pre.value.length--
    }
  }

  const handleNext = () => {
    if (next.value.length > 0) {
      pre.value.push({
        id: new Date().getTime(),
        data: next.value[next.value.length - 1],
      })
      ctx.value?.putImageData(
        next.value[next.value.length - 1] as ImageData,
        0,
        0
      )
      next.value.length--
    }
  }

  return {
    el,
    CANVAS_WIDTH,
    CANVAS_HEIGHT,
    allowDownload,
    lineWidth,
    lineStyle,
    reportURL,
    handleMouseDown,
    handleMouseMove,
    handleMouseUp,
    handleTouchStart,
    handleTouchMove,
    handleTouchEnd,
    handleRemove,
    handleSave,
    handlePrevious,
    handleNext,
    initCanvasCtx,
  }
}
